package com.xyz.wll.es.manager.ui.frame;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.xyz.wll.es.manager.ui.filter.CsvFileFilter;
import com.xyz.wll.es.manager.ui.filter.JsonFileFilter;
import com.xyz.wll.es.manager.ui.model.PageCursor;
import com.xyz.wll.es.manager.ui.utils.UiUtils;
import com.xyz.wll.es.manager.ui.config.EsConnectConfig;
import com.xyz.wll.es.manager.ui.model.AppendableTableModel;
import com.xyz.wll.es.manager.ui.model.MyTableModel;
import com.xyz.wll.es.util.EsUtil;
import com.xyz.wll.es.util.ProcessFeedback;
import com.xyz.wll.es.util.QueryCondition;
import com.xyz.wll.es.util.model.DocRecord;
import com.xyz.wll.es.util.model.EsSearchResult;
import com.xyz.wll.es.util.model.EsSqlTableRecord;
import com.xyz.wll.es.util.model.IndexDetail;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.*;

public class MainFrame extends JFrame {

    //DATA ELEMENTS
    //配置相关
    private Properties properties = new Properties();
    private List<EsConnectConfig> esConnectConfigList = new ArrayList<>();
    private String selectedCopyIndex;

    //查询相关
    private EsUtil esUtil = new EsUtil();
    private PageCursor pageCursor = new PageCursor();
    private List<QueryCondition> queryConditionList = new ArrayList<>();
    private Map<String,String> fieldsMappings;

    //线程池
    private ExecutorService executorService = Executors.newCachedThreadPool();

    //UI ELEMENTS
    JMenuBar mainMenuBar;
    JMenuItem aboutMenuItem;

    private JPanel mainPanel;

    private JPanel topPanel;
    private JComboBox schema;
    private JComboBox esCluster;
    private JTextField connectUserName;
    private JPasswordField connectPassword;
    private JButton connectButton;

    private JPanel centerPanel;

    private JScrollPane leftPanel;
    private JList esIndexs;
    private JPopupMenu esIndexsPopMenu;
    private JMenuItem createIndexMenuItem;
    private JMenuItem deleteIndexMenuItem;
    private JMenuItem truncateIndexMenuItem;
    private JMenuItem copyIndexMenuItem;
    private JMenuItem copyIndexDataMenuItem;
    private JMenuItem pasteIndexDataMenuItem;
    private JMenuItem backupIndexMenuItem;
    private JMenuItem importDataMenuItem;
    private JMenuItem exportDataMenuItem;

    private JPanel rightPanel;
    private JTabbedPane tabbedPane1;

    private JPanel dataPanel;
    private JScrollPane dataViewScrollPanel;
    private JTable dataTable;

    private JPopupMenu dataTablePopMenu;
    private JMenuItem copyLine;
    private JMenuItem pasteLine;
    private JMenuItem exportToCsvMenuItem;
    private JMenuItem importFromCsvMenuItem;

    private JToolBar dataViewToolBar;
    private JButton firstPage;
    private JButton priorPage;
    private JButton nextPage;
    private JButton lastPage;
    private JButton addRecord;
    private JButton removeRecord;
    private JButton filterButton;
    private JButton filterButtonAdd;
    private JButton filterButtonSub;
    private JButton filterButtonApply;
    private JButton filterButtonClear;

    private JScrollPane dataFilterPanel;
    private JTable queryConditions;
    private JLabel queryConditionsText;

    private JPanel mappingsPanel;
    private JScrollPane fieldsScrollPanel;
    private JTable fieldsTable;
    private JToolBar fieldsToolBar;
    private JButton addField;
    private JButton removeField;
    private JButton applyMappings;
    private JButton reloadMappings;
    private JPopupMenu fieldsTablePopupMenu;
    private JMenuItem exportMappingsMenuItem;
    private JMenuItem importMappingsMenuItem;

    private JPanel settingPanel;
    private JTextArea indexSettings;
    private JButton applySettings;
    private JButton reloadSettings;

    private JPanel sqlPanel;
    private JTextArea sqlTextArea;
    private JTable sqlQueryTable;

    private JPopupMenu sqlTextAreaPopMenu;
    private JMenuItem runAllMenuItem;
    private JMenuItem runSelectMenuItem;

    private JPanel bottomPanel;
    private JScrollPane statusPanel;
    private JTextArea statusInfo;
    private JScrollPane progressBarPanel;
    private JList progressBarList;



    private void createUIComponents() {
        // TODO: place custom component creation code here
        this.setTitle("ES数据管理工具");

        mainMenuBar = new JMenuBar();
        aboutMenuItem = new JMenuItem("版本信息");
        mainMenuBar.add(aboutMenuItem);
        this.setJMenuBar(mainMenuBar);

        mainPanel = new JPanel();
        this.setContentPane(mainPanel);

        mainPanel.setLayout(new GridLayoutManager(3, 2, new Insets(0, 0, 0, 0), -1, -1));
        {
            //topPanel
            topPanel = new JPanel();
            topPanel.setLayout(new GridLayoutManager(1, 8, new Insets(0, 0, 0, 0), -1, -1));
            mainPanel.add(topPanel, new GridConstraints(0, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
            {
                //connect schema
                schema = new JComboBox();
                final DefaultComboBoxModel defaultComboBoxModel2 = new DefaultComboBoxModel();
                defaultComboBoxModel2.addElement("http");
                defaultComboBoxModel2.addElement("https");
                schema.setModel(defaultComboBoxModel2);
                topPanel.add(schema, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                //connect clusters
                esCluster = new JComboBox();
                esCluster.setEditable(true);
                final DefaultComboBoxModel defaultComboBoxModel1 = new DefaultComboBoxModel();
                esCluster.setModel(defaultComboBoxModel1);
                topPanel.add(esCluster, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                //connect userName
                final JLabel label2 = new JLabel();
                label2.setText("用户");
                topPanel.add(label2, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                connectUserName = new JTextField();
                connectUserName.setColumns(8);
                topPanel.add(connectUserName, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                //connect password
                final JLabel label3 = new JLabel();
                label3.setText("密码");
                topPanel.add(label3, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                connectPassword = new JPasswordField();
                connectPassword.setColumns(8);
                connectPassword.setEchoChar('*');
                topPanel.add(connectPassword, new GridConstraints(0, 6, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                //connect button
                connectButton = new JButton();
                connectButton.setHorizontalAlignment(0);
                connectButton.setText("连接");
                topPanel.add(connectButton, new GridConstraints(0, 7, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
            }

            //center panel
            centerPanel = new JPanel();
            centerPanel.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
            mainPanel.add(centerPanel, new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
            {
                //left panel
                leftPanel = new JScrollPane();
                centerPanel.add(leftPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
                {
                    esIndexs = new JList();
                    leftPanel.setViewportView(esIndexs);
                    {
                        esIndexsPopMenu = new JPopupMenu();
                        createIndexMenuItem = new JMenuItem("新建");
                        deleteIndexMenuItem = new JMenuItem("删除");
                        truncateIndexMenuItem = new JMenuItem("清空数据");
                        copyIndexMenuItem = new JMenuItem("复制新建");
                        copyIndexDataMenuItem = new JMenuItem("复制数据");
                        pasteIndexDataMenuItem = new JMenuItem("粘贴数据");
                        backupIndexMenuItem = new JMenuItem("备份索引");
                        importDataMenuItem = new JMenuItem("导入数据");
                        exportDataMenuItem = new JMenuItem("导出数据");
                        esIndexsPopMenu.add(createIndexMenuItem);
                        esIndexsPopMenu.add(deleteIndexMenuItem);
                        esIndexsPopMenu.add(truncateIndexMenuItem);
                        esIndexsPopMenu.add(copyIndexMenuItem);
                        esIndexsPopMenu.add(copyIndexDataMenuItem);
                        esIndexsPopMenu.add(pasteIndexDataMenuItem);
                        esIndexsPopMenu.add(backupIndexMenuItem);
                        esIndexsPopMenu.add(importDataMenuItem);
                        esIndexsPopMenu.add(exportDataMenuItem);
                        esIndexs.setComponentPopupMenu(esIndexsPopMenu);
                    }
                }

                //right panel
                rightPanel = new JPanel();
                rightPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
                centerPanel.add(rightPanel, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
                {
                    //tabbed panel
                    tabbedPane1 = new JTabbedPane();
                    rightPanel.add(tabbedPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(400, 200), null, 0, false));
                    {
                        //data panel
                        dataPanel = new JPanel();
                        dataPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1));
                        tabbedPane1.addTab("表数据", dataPanel);
                        {
                            //data view scroll panel
                            dataViewScrollPanel = new JScrollPane();
                            dataPanel.add(dataViewScrollPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
                            {
                                dataTable = new JTable();
                                dataTable.setAutoCreateRowSorter(false);
                                dataTable.setAutoResizeMode(0);
                                dataTable.setSurrendersFocusOnKeystroke(true);
                                dataViewScrollPanel.setViewportView(dataTable);
                                {
                                    dataTablePopMenu = new JPopupMenu("dataTablePopMenu");
                                    copyLine = new JMenuItem("拷贝");
                                    pasteLine = new JMenuItem("粘贴");
                                    exportToCsvMenuItem = new JMenuItem("导出");
                                    importFromCsvMenuItem = new JMenuItem("导入");
                                    dataTablePopMenu.add(copyLine);
                                    dataTablePopMenu.add(pasteLine);
                                    dataTablePopMenu.add(importFromCsvMenuItem);
                                    dataTablePopMenu.add(exportToCsvMenuItem);
                                    dataTable.setComponentPopupMenu(dataTablePopMenu);
                                    dataViewScrollPanel.setComponentPopupMenu(dataTablePopMenu);
                                }
                            }

                            //data view tool bar
                            dataViewToolBar = new JToolBar();
                            dataPanel.add(dataViewToolBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
                            {
                                //first page button
                                firstPage = new JButton();
                                firstPage.setEnabled(false);
                                firstPage.setText("|<");
                                dataViewToolBar.add(firstPage);

                                //prior page button
                                priorPage = new JButton();
                                priorPage.setEnabled(false);
                                priorPage.setText("<<");
                                dataViewToolBar.add(priorPage);

                                //next page button
                                nextPage = new JButton();
                                nextPage.setEnabled(false);
                                nextPage.setText(">>");
                                dataViewToolBar.add(nextPage);

                                //last page button
                                lastPage = new JButton();
                                lastPage.setEnabled(false);
                                lastPage.setText(">|");
                                dataViewToolBar.add(lastPage);

                                //separator1
                                final JToolBar.Separator toolBar$Separator1 = new JToolBar.Separator();
                                dataViewToolBar.add(toolBar$Separator1);

                                //add record button
                                addRecord = new JButton();
                                addRecord.setEnabled(false);
                                addRecord.setText("+");
                                dataViewToolBar.add(addRecord);

                                //remove record button
                                removeRecord = new JButton();
                                removeRecord.setEnabled(false);
                                removeRecord.setText("-");
                                dataViewToolBar.add(removeRecord);

                                //separator2
                                final JToolBar.Separator toolBar$Separator2 = new JToolBar.Separator();
                                dataViewToolBar.add(toolBar$Separator2);

                                //filter button
                                filterButton = new JButton();
                                filterButton.setEnabled(true);
                                filterButton.setText("↑");
                                dataViewToolBar.add(filterButton);

                                //add filter condition button
                                filterButtonAdd = new JButton();
                                filterButtonAdd.setEnabled(false);
                                filterButtonAdd.setVisible(false);
                                filterButtonAdd.setText("添加过滤条件");
                                dataViewToolBar.add(filterButtonAdd);

                                //remove filter condition button
                                filterButtonSub = new JButton();
                                filterButtonSub.setEnabled(false);
                                filterButtonSub.setVisible(false);
                                filterButtonSub.setText("删除过滤条件");
                                dataViewToolBar.add(filterButtonSub);

                                //clear filter conditions button
                                filterButtonClear = new JButton();
                                filterButtonClear.setEnabled(false);
                                filterButtonClear.setVisible(false);
                                filterButtonClear.setText("清空过滤条件");
                                dataViewToolBar.add(filterButtonClear);

                                //apply filter conditions button
                                filterButtonApply = new JButton();
                                filterButtonApply.setEnabled(false);
                                filterButtonApply.setVisible(false);
                                filterButtonApply.setText("应用过滤条件");
                                dataViewToolBar.add(filterButtonApply);
                            }

                            //data view filter panel
                            dataFilterPanel = new JScrollPane();
                            dataFilterPanel.setVisible(false);
                            dataPanel.add(dataFilterPanel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
                            {
                                //query conditions table
                                queryConditions = new JTable();
                                queryConditions.setAutoCreateRowSorter(false);
                                queryConditions.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
                                dataFilterPanel.setViewportView(queryConditions);
                            }

                            //query conditions label
                            queryConditionsText = new JLabel();
                            queryConditionsText.setVisible(false);
                            queryConditionsText.setText(" ");
                            dataPanel.add(queryConditionsText, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
                        }

                        //mappings panel
                        mappingsPanel = new JPanel();
                        mappingsPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
                        tabbedPane1.addTab("表结构", mappingsPanel);
                        {
                            //fields view scroll panel
                            fieldsScrollPanel = new JScrollPane();
                            mappingsPanel.add(fieldsScrollPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
                            {
                                //fields table
                                fieldsTable = new JTable();
                                fieldsTable.setAutoCreateRowSorter(false);
                                fieldsTable.setAutoResizeMode(4);
                                fieldsTable.setSurrendersFocusOnKeystroke(true);
                                fieldsScrollPanel.setViewportView(fieldsTable);
                                {
                                    fieldsTablePopupMenu = new JPopupMenu();
                                    importMappingsMenuItem = new JMenuItem("导入");
                                    exportMappingsMenuItem = new JMenuItem("导出");
                                    fieldsTablePopupMenu.add(importMappingsMenuItem);
                                    fieldsTablePopupMenu.add(exportMappingsMenuItem);
                                    fieldsTable.setComponentPopupMenu(fieldsTablePopupMenu);
                                    fieldsScrollPanel.setComponentPopupMenu(fieldsTablePopupMenu);
                                }
                            }


                            //fields view tool bar
                            fieldsToolBar = new JToolBar();
                            mappingsPanel.add(fieldsToolBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
                            {
                                //add field button
                                addField = new JButton();
                                addField.setEnabled(false);
                                addField.setText("添加");
                                fieldsToolBar.add(addField);

                                //remove field button
                                removeField = new JButton();
                                removeField.setEnabled(false);
                                removeField.setText("删除");
                                fieldsToolBar.add(removeField);

                                //apply mappings button
                                applyMappings = new JButton();
                                applyMappings.setEnabled(false);
                                applyMappings.setText("应用");
                                fieldsToolBar.add(applyMappings);

                                //reload mappings button
                                reloadMappings = new JButton();
                                reloadMappings.setEnabled(false);
                                reloadMappings.setText("刷新");
                                fieldsToolBar.add(reloadMappings);
                            }

                        }

                        //settings panel
                        settingPanel = new JPanel();
                        settingPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
                        tabbedPane1.addTab("表设置", settingPanel);
                        {
                            //settings scroll panel
                            final JScrollPane settingsScrollPanel = new JScrollPane();
                            settingPanel.add(settingsScrollPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
                            {
                                //index settings text area
                                indexSettings = new JTextArea();
                                settingsScrollPanel.setViewportView(indexSettings);
                            }

                            //settings tool bar
                            final JToolBar settingsToolBar = new JToolBar();
                            settingPanel.add(settingsToolBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
                            {
                                //apply settings button
                                applySettings = new JButton();
                                applySettings.setEnabled(false);
                                applySettings.setText("应用");
                                settingsToolBar.add(applySettings);

                                //reload settings button
                                reloadSettings = new JButton();
                                reloadSettings.setEnabled(false);
                                reloadSettings.setText("刷新");
                                settingsToolBar.add(reloadSettings);
                            }
                        }

                        //sql panel
                        sqlPanel = new JPanel();
                        sqlPanel.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1));
                        tabbedPane1.addTab("sql查询", sqlPanel);
                        {
                            //sql query scroll panel
                            final JScrollPane scrollPane2 = new JScrollPane();
                            sqlPanel.add(scrollPane2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(0, 67), null, 0, false));
                            {
                                //sql text area
                                sqlTextArea = new JTextArea();
                                sqlTextArea.setEnabled(false);
                                sqlTextArea.setText("");
                                scrollPane2.setViewportView(sqlTextArea);
                                {
                                    sqlTextAreaPopMenu = new JPopupMenu("sql");
                                    runAllMenuItem = new JMenuItem("运行所有sql");
                                    runSelectMenuItem = new JMenuItem("运行选中的sql");
                                    sqlTextAreaPopMenu.add(runAllMenuItem);
                                    sqlTextAreaPopMenu.add(runSelectMenuItem);
                                    sqlTextArea.setComponentPopupMenu(sqlTextAreaPopMenu);
                                }
                            }

                            //separator
                            final JSeparator separator1 = new JSeparator();
                            sqlPanel.add(separator1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

                            //sql result scroll panel
                            final JScrollPane scrollPane3 = new JScrollPane();
                            sqlPanel.add(scrollPane3, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
                            {
                                sqlQueryTable = new JTable();
                                sqlQueryTable.setAutoResizeMode(0);
                                scrollPane3.setViewportView(sqlQueryTable);
                            }

                        }
                    }
                }
            }

            bottomPanel = new JPanel();
            bottomPanel.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
            mainPanel.add(bottomPanel, new GridConstraints(2, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(0, 60), null, 0, false));
            {
                statusPanel = new JScrollPane();
                bottomPanel.add(statusPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(0, 60), null, 0, false));

                statusInfo = new JTextArea();
                statusInfo.setLineWrap(true);
                statusInfo.setEnabled(false);
                statusInfo.setDisabledTextColor(Color.BLACK);
                statusPanel.setViewportView(statusInfo);

                progressBarPanel = new JScrollPane();
                bottomPanel.add(progressBarPanel, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(0, 60), null, 0, false));

                progressBarList = new JList<JProgressBar>();
                progressBarList.setModel(new DefaultListModel<JProgressBar>());
                progressBarList.setCellRenderer(new ListCellRenderer() {
                    @Override
                    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                        return (JProgressBar) value;
                    }
                });
                progressBarPanel.setViewportView(progressBarList);

            }
        }

    }

    private void addActionListeners() {
        aboutMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //JOptionPane.showMessageDialog(aboutMenuItem, "作者:wll,\n 版本: 1.0.0,\n 更改历史: 添加基本功能","版本信息",JOptionPane.INFORMATION_MESSAGE);

                AboutFrame aboutFrame = new AboutFrame();
                aboutFrame.setLocation(400, 200);
                aboutFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
                aboutFrame.pack();
                aboutFrame.setVisible(true);

            }
        });

        {
            esCluster.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println(e);
                    if ("comboBoxChanged".equals(e.getActionCommand())) {
                        for (EsConnectConfig esConnectConfig : esConnectConfigList) {
                            if (esCluster.getSelectedItem().toString().equals(esConnectConfig.getHosts())) {
                                schema.setSelectedItem(esConnectConfig.getSchema());
                                connectUserName.setText(esConnectConfig.getUsername());
                                connectPassword.setText(esConnectConfig.getPassword());
                                break;
                            }
                        }
                    }
                }
            });

            connectButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    boolean newItemFlag = false;

                    {
                        int i = 0;
                        for (i = 0; i < esCluster.getModel().getSize(); i++) {
                            if (esCluster.getModel().getElementAt(i).equals(esCluster.getSelectedItem())) {
                                break;
                            }
                        }
                        newItemFlag = i >= esCluster.getModel().getSize();
                    }

                    try {
                        if (esUtil.connect(esCluster.getSelectedItem().toString(), schema.getSelectedItem().toString(), connectUserName.getText(), new String(connectPassword.getPassword()))) {

                            if (newItemFlag) {
                                DefaultComboBoxModel defaultComboBoxModel = (DefaultComboBoxModel) (esCluster.getModel());
                                defaultComboBoxModel.addElement(esCluster.getSelectedItem());
                                EsConnectConfig esConnectConfig = new EsConnectConfig();
                                esConnectConfig.setHosts(esCluster.getSelectedItem().toString());
                                esConnectConfig.setSchema(schema.getSelectedItem().toString());
                                esConnectConfig.setUsername(connectUserName.getText());
                                esConnectConfig.setPassword(new String(connectPassword.getPassword()));
                                esConnectConfigList.add(esConnectConfig);

                                properties.put("esClusters", JSONArray.toJSONString(esConnectConfigList));
                                saveProperties();
                            }

                            Map<String, IndexDetail> indicesDetail = esUtil.getIndices();
                            List<String> activeIndicesName = new ArrayList<>();
                            for (String index : indicesDetail.keySet()) {
                                IndexDetail indexDetail = indicesDetail.get(index);
                                if (indexDetail.getStatus().equals("open")) {
                                    if(!indexDetail.getHealth().equals("red")) {
                                        activeIndicesName.add(index);
                                    }
                                }
                            }
                            DefaultListModel<String> defaultListModel = new DefaultListModel<>();
                            for (String item : activeIndicesName) {
                                defaultListModel.addElement(item);
                            }
                            esIndexs.setModel(defaultListModel);
                            esIndexs.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                            esIndexs.setEnabled(true);

                            sqlTextArea.setEnabled(true);

                            statusInfo.append("\n" + indicesDetail.size() + "索引加载成功");
                        } else {
                            esIndexs.setEnabled(false);
                            disableIndex();
                            statusInfo.append("\n" + esCluster.getSelectedItem() + "连接失败!!!");
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        esIndexs.setEnabled(false);
                        disableIndex();
                        statusInfo.append("\n" + ex.getMessage());
                    }
                }
            });

            esIndexs.addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e) {

                    if(e.getValueIsAdjusting()) {

                        if (esIndexs.getSelectedValue() == null) {
                            disableIndex();
                            return;
                        }

                        String indexName = esIndexs.getSelectedValue().toString();
                        try {
                            //if (esUtil.connect(esCluster.getSelectedItem().toString(),schema.getSelectedItem().toString(),connectUserName.getText(),new String(connectPassword.getPassword()))) {

                            pageCursor.setIndex(indexName);
                            pageCursor.gotoFirstPage();

                            statusInfo.append("\n" + indexName + "加载数据中...");
                            initQueryConditions();
                            showPageData();
                            statusInfo.append("\n" + indexName + "数据加载完毕,总共" + pageCursor.getTotal() + "条数据。");

                            showTableFields();

                            showIndexSettings();
                            //} else {
                            //    statusInfo.append("\n" + indexName + "数据加载失败!!!");
                            //}
                        } catch (Exception e1) {
                            e1.printStackTrace();
                            statusInfo.append("\n" + "连接" + esCluster.getSelectedItem().toString() + "失败");
                        }
                    }
                }
            });
        }

        {
            createIndexMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {

                    String indexName = JOptionPane.showInputDialog("请输入新建索引名称:");
                    if (indexName != null) {
                        DefaultListModel<String> model = (DefaultListModel<String>) esIndexs.getModel();
                        model.addElement(indexName);
                        esIndexs.updateUI();
                        if (esUtil.createIndex(indexName)) {
                            statusInfo.append("\n" + String.format("%s创建成功", indexName));
                        } else {
                            statusInfo.append("\n" + String.format("%s创建失败", indexName));
                        }
                    }
                }
            });

            deleteIndexMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Object selectedItem = esIndexs.getSelectedValue();
                    if (selectedItem != null) {
                        if (esUtil.deleteIndex(selectedItem.toString())) {
                            DefaultListModel<String> model = (DefaultListModel<String>) esIndexs.getModel();
                            String index = model.remove(esIndexs.getSelectedIndex());
                            esIndexs.updateUI();
                            statusInfo.append("\n" + index + "删除成功");
                        } else {
                            statusInfo.append("\n" + selectedItem.toString() + "删除失败");
                        }
                    } else {
                        statusInfo.append("\n" + "请选取索引名称");
                    }
                }
            });

            truncateIndexMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Object selectedItem = esIndexs.getSelectedValue();
                    if(selectedItem != null) {
                        String index = selectedItem.toString();
                        if (esUtil.truncateIndex(index)) {
                            statusInfo.append("\n" + String.format("%s索引数据已经清空", index));
                        } else {
                            statusInfo.append("\n" + String.format("清空%s索引数据失败", index));
                        }
                    } else {
                        statusInfo.append("\n" + "请选取索引名称");
                    }
                }
            });

            copyIndexMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Object selectedItem = esIndexs.getSelectedValue();
                    if(selectedItem != null) {
                        String index = selectedItem.toString();
                        String destIndex = JOptionPane.showInputDialog("请输入新建索引名称:");
                        if (destIndex != null) {
                            if(!esUtil.existIndex(destIndex)) {
                                if (esUtil.copyCreateIndex(index, destIndex)) {
                                    statusInfo.append("\n" + String.format("%s索引创建成功", destIndex));
                                } else {
                                    statusInfo.append("\n" + String.format("%s索引创建失败", destIndex));
                                }
                            } else {
                                statusInfo.append("\n" + String.format("%s索引已经存在,请先删除", destIndex));
                            }
                        }
                    }  else {
                        statusInfo.append("\n" + "请选取索引名称");
                    }
                }
            });

            copyIndexDataMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Object selectedItem = esIndexs.getSelectedValue();
                    if(selectedItem != null) {
                        String index = selectedItem.toString();
                        selectedCopyIndex = index;
                        statusInfo.append("\n" + String.format("已经选取%s索引进行数据复制", selectedCopyIndex));
                    }  else {
                        statusInfo.append("\n" + "请选取索引名称");
                    }
                }
            });

            pasteIndexDataMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Object selectedItem = esIndexs.getSelectedValue();
                    if(selectedItem != null) {
                        String destIndex = selectedItem.toString();
                        if(esUtil.copyIndexData(selectedCopyIndex, destIndex)) {
                            statusInfo.append("\n" + String.format("拷贝数据: %s => %s", selectedCopyIndex, destIndex));
                        } else {
                            statusInfo.append("\n" + String.format("拷贝数据失败: %s => %s", selectedCopyIndex, destIndex));
                        }
                    }  else {
                        statusInfo.append("\n" + "请选取索引名称");
                    }
                }
            });

            backupIndexMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Object selectedItem = esIndexs.getSelectedValue();
                    if(selectedItem != null) {
                        String index = selectedItem.toString();
                        String destIndex = JOptionPane.showInputDialog("请输入新建索引名称:");
                        if (destIndex != null) {
                            if(!esUtil.existIndex(destIndex)) {
                                if (esUtil.copyCreateIndex(index, destIndex)) {
                                    statusInfo.append("\n" + String.format("%s索引创建成功", destIndex));
                                    if(esUtil.copyIndexData(index, destIndex)) {
                                        statusInfo.append("\n" + String.format("备份数据: %s => %s", index, destIndex));
                                    } else {
                                        statusInfo.append("\n" + String.format("备份数据失败: %s => %s", index, destIndex));
                                    }
                                } else {
                                    statusInfo.append("\n" + String.format("%s索引创建失败", destIndex));
                                }
                            } else {
                                statusInfo.append("\n" + String.format("%s索引已经存在,请先删除", destIndex));
                            }
                        }
                    }  else {
                        statusInfo.append("\n" + "请选取索引名称");
                    }
                }
            });

            importDataMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    String index = (String) esIndexs.getSelectedValue();
                    if (index != null) {
                        JFileChooser fileChooser = new JFileChooser();
                        int result = fileChooser.showOpenDialog(importDataMenuItem);
                        if (result == JFileChooser.APPROVE_OPTION) {
                            String filepath = fileChooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                            System.out.println(filepath);
                            executorService.execute(new Runnable() {
                                @Override
                                public void run() {
                                    statusInfo.append("\n" + String.format("从文件%s导入数据记录到索引%s...", filepath, index));
                                    JProgressBar progressBar = new JProgressBar();
                                    DefaultListModel<JProgressBar> model = (DefaultListModel<JProgressBar>) progressBarList.getModel();
                                    model.addElement(progressBar);
                                    progressBarPanel.updateUI();
                                    long records = esUtil.importData(index, filepath, new ProcessFeedback() {
                                        @Override
                                        public void reportPercent(float percent) {
                                            int progress = (int) (percent * 100);
                                            System.out.println(String.format("%d%%", progress));
                                            progressBar.setValue(progress);
                                            if (progress == 100) {
                                                model.removeElement(progressBar);
                                            }
                                            progressBarPanel.updateUI();
                                        }

                                        @Override
                                        public void reportMessage(String message) {
                                            statusInfo.append("\n" + message);
                                        }
                                    });
                                    if (records >= 0) {
                                        statusInfo.append("\n" + String.format("从文件%s导入%d条数据记录到索引%s", filepath, records, index));
                                    }
                                }
                            });
                        }
                    }
                }
            });

            exportDataMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    String index = (String) esIndexs.getSelectedValue();
                    if (index != null) {
                        JFileChooser fileChooser = new JFileChooser();
                        int result = fileChooser.showSaveDialog(exportDataMenuItem);
                        if (result == JFileChooser.APPROVE_OPTION) {
                            String filepath = fileChooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                            System.out.println(filepath);
                            executorService.execute(new Runnable() {
                                @Override
                                public void run() {
                                    statusInfo.append("\n" + String.format("从索引%s导出数据记录到文件%s...", index, filepath));
                                    JProgressBar progressBar = new JProgressBar();
                                    DefaultListModel<JProgressBar> model = (DefaultListModel<JProgressBar>) progressBarList.getModel();
                                    model.addElement(progressBar);
                                    progressBarPanel.updateUI();

                                    long n = esUtil.exportData(index, filepath, new ProcessFeedback() {
                                        @Override
                                        public void reportPercent(float percent) {
                                            int progress = (int) (percent * 100);
                                            System.out.println(String.format("%d%%", progress));
                                            progressBar.setValue(progress);
                                            if (progress == 100) {
                                                model.removeElement(progressBar);
                                            }
                                            progressBarPanel.updateUI();
                                        }

                                        @Override
                                        public void reportMessage(String message) {
                                            statusInfo.append("\n" + message);
                                        }
                                    });
                                    statusInfo.append("\n" + String.format("从索引%s导出%d条数据记录到文件%s", index, n, filepath));
                                }
                            });
                        }
                    }
                }
            });
        }

        tabbedPane1.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                System.out.println(e.toString());
            }
        });

        {
            firstPage.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    pageCursor.gotoFirstPage();
                    showPageData();
                }
            });

            priorPage.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    pageCursor.gotoPriorPage();
                    showPageData();
                }
            });

            nextPage.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    pageCursor.gotoNextPage();
                    showPageData();
                }
            });

            lastPage.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    pageCursor.gotoLastPage();
                    showPageData();
                }
            });

            addRecord.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JTable table = dataTable;
                    MyTableModel model = (MyTableModel) dataTable.getModel();
                    if (table.getCellEditor() != null && table.getRowCount() > 0) {
                        table.getCellEditor().stopCellEditing();
                    }

                    int selectRow = table.getSelectedRow();
                    selectRow = selectRow == TableModelEvent.ALL_COLUMNS ? table.getRowCount() - 1 : selectRow;

                    model.addRow(selectRow + 1);
                    //table.addRowSelectionInterval(selectRow + 1, selectRow + 1);
                    table.setRowSelectionInterval(selectRow + 1, selectRow + 1);
                    table.editCellAt(selectRow + 1, 0);
                }
            });

            removeRecord.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JTable table = dataTable;
                    MyTableModel model = (MyTableModel) dataTable.getModel();
                    if (table.getCellEditor() != null && table.getRowCount() > 0) {
                        table.getCellEditor().stopCellEditing();
                    }

                    int selectRow = table.getSelectedRow();
                    int selectRowCount = table.getSelectedRowCount();
                    if (selectRow > -1 && selectRowCount > 0) {
                        model.removeRows(selectRow, selectRow + selectRowCount - 1);
                        //table.removeRowSelectionInterval(selectRow, selectRow + selectRowCount - 1);
                    }
                }
            });
        }

        {
            copyLine.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println(e);
                    MyTableModel model = (MyTableModel) dataTable.getModel();
                    List<String> lines = new ArrayList<>();
                    for (int i : dataTable.getSelectedRows()) {
                        List<String> fields = new ArrayList<>();
                        for (int j = 0; j < model.getColumnCount(); j++) {
                            Object value = model.getValueAt(i, j);
                            if (value == null) {
                                fields.add("");
                            } else {
                                fields.add(value.toString());
                            }
                        }
                        lines.add(String.join("\t", fields));
                    }
                    String text = String.join("\n", lines);
                    System.out.println(text);
                    UiUtils.setClipboardString(text);
                    statusInfo.append("\n" + String.format("复制了%d行记录", dataTable.getSelectedRowCount()));
                }
            });

            pasteLine.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println(e);
                    MyTableModel model = (MyTableModel) dataTable.getModel();
                    String text = UiUtils.getClipboardString();
                    System.out.println(text);
                    String[] lines = Split(text,'\n');
                    System.out.println(lines.length);
                    if (lines.length == dataTable.getSelectedRowCount()) {
                        for (int i = 0; i < dataTable.getSelectedRowCount(); i++) {
                            String line = lines[i];
                            String[] fields = Split(line, '\t');
                            model.updateRow(dataTable.getSelectedRow() + i, fields);
                        }
                        statusInfo.append("\n" + String.format("粘贴更新了%d行记录", lines.length));
                    } else {
                        statusInfo.append("\n" + String.format("剪贴板中的记录数[%d] != 选中的记录数[%d]", lines.length, dataTable.getSelectedRowCount()));
                    }
                }
            });

            exportToCsvMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFileChooser fileChooser = new JFileChooser();
                    int result = fileChooser.showSaveDialog(exportToCsvMenuItem);
                    if (result == JFileChooser.APPROVE_OPTION) {
                        String filepath = fileChooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                        System.out.println(filepath);
                        exportToCsv((MyTableModel) dataTable.getModel(), filepath);
                        statusInfo.append("\n" + String.format("数据记录导出到文件%s", filepath));
                    }
                }
            });

            importFromCsvMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFileChooser fileChooser = new JFileChooser();
                    int result = fileChooser.showOpenDialog(importFromCsvMenuItem);
                    if (result == JFileChooser.APPROVE_OPTION) {
                        String filepath = fileChooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                        System.out.println(filepath);
                        int records = importFromCsv((MyTableModel) dataTable.getModel(), filepath);
                        if (records >= 0) {
                            statusInfo.append("\n" + String.format("从文件%s导入%d条数据记录", filepath, records));
                        }
                    }
                }
            });
        }

        {
            filterButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    dataFilterPanel.setVisible(!dataFilterPanel.isVisible());
                    if(dataFilterPanel.isVisible()) {
                        filterButton.setText("↓");
                        filterButtonAdd.setVisible(true);
                        filterButtonSub.setVisible(true);
                        filterButtonClear.setVisible(true);
                        filterButtonApply.setVisible(true);
                        queryConditionsText.setVisible(true);
                    } else {
                        filterButton.setText("↑");
                        filterButtonAdd.setVisible(false);
                        filterButtonSub.setVisible(false);
                        filterButtonClear.setVisible(false);
                        filterButtonApply.setVisible(false);
                        queryConditionsText.setVisible(false);
                    }
                    dataPanel.updateUI();
                }
            });

            filterButtonAdd.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    DefaultTableModel model = (DefaultTableModel) queryConditions.getModel();
                    model.insertRow(queryConditions.getRowCount(), new String[]{});
                }
            });

            filterButtonSub.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    DefaultTableModel model = (DefaultTableModel) queryConditions.getModel();
                    for (int i = 0; i < queryConditions.getSelectedRowCount(); i++) {
                        int row = queryConditions.getSelectedRow() + i;
                        model.removeRow(row);
                    }
                }
            });

            filterButtonClear.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    DefaultTableModel model = (DefaultTableModel) queryConditions.getModel();
                    for (int i = model.getRowCount() - 1; i >= 0; i--) {
                        model.removeRow(i);
                    }
                }
            });

            filterButtonApply.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    List<String> conditions = new ArrayList<>();
                    queryConditionList.clear();
                    for (int row = 0; row < queryConditions.getRowCount(); row++) {
                        String field = (String) queryConditions.getValueAt(row, 0);
                        String compare = (String) queryConditions.getValueAt(row, 1);
                        String value = (String) queryConditions.getValueAt(row, 2);
                        Boolean apply = (Boolean) queryConditions.getValueAt(row, 3);
                        if (apply) {
                            conditions.add(field + compare + value);
                            QueryCondition queryCondition = new QueryCondition();
                            queryCondition.setField(field);
                            queryCondition.setCompare(compare);
                            queryCondition.setValue(value);
                            queryConditionList.add(queryCondition);
                        }
                    }
                    System.out.println(String.join(" AND ", conditions));
                    queryConditionsText.setText(String.join(" AND ", conditions));

                    pageCursor.gotoFirstPage();
                    showPageData();
                }
            });
        }

        {
            addField.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    DefaultTableModel model = (DefaultTableModel) fieldsTable.getModel();
                    model.addRow(new String[2]);
                    fieldsTable.setRowSelectionInterval(fieldsTable.getRowCount()-1, fieldsTable.getRowCount()-1);
                    fieldsTable.editCellAt(fieldsTable.getRowCount()-1, 0);
                }
            });

            removeField.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(fieldsTable.getSelectedRowCount() > 0) {
                        DefaultTableModel model = (DefaultTableModel) fieldsTable.getModel();
                        for(int i = fieldsTable.getSelectedRowCount()-1; i >= 0; i--) {
                            int row = fieldsTable.getSelectedRow() + i;
                            if(fieldsTable.isCellEditable(row,0)) {
                                model.removeRow(row);
                            } else {
                                statusInfo.append("\n" + String.format("第%d行不是新增行,不能编辑！！！", row));
                            }
                        }

                    }
                }
            });

            applyMappings.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        DefaultTableModel model = (DefaultTableModel) fieldsTable.getModel();
                        Vector dataVector = model.getDataVector();
                        Map<String, String> fieldMappings = new TreeMap<>();
                        for (int i = 0; i < dataVector.size(); i++) {
                            Vector<String> item = (Vector<String>) dataVector.get(i);
                            String field = item.get(0);
                            String type = item.get(1);
                            if (field == null || type == null) {
                                statusInfo.append("\n" + String.format("第%d行数据字段名或字段类型为空", i + 1));
                                return;
                            }
                            fieldMappings.put(field, type);
                        }

                        boolean op = esUtil.setMappings(esIndexs.getSelectedValue().toString(), fieldMappings);
                        if (op) {
                            statusInfo.append("\n" + "索引" + esIndexs.getSelectedValue().toString() + "的表结构更新成功");
                        } else {
                            statusInfo.append("\n" + "索引" + esIndexs.getSelectedValue().toString() + "的表结构更新失败");
                        }

                        showTableFields();
                    } catch (Throwable ex) {
                        ex.printStackTrace();
                        System.out.println(ex.getMessage());
                        statusInfo.append("\n" + ex.getMessage());
                    }
                }
            });

            reloadMappings.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    showTableFields();
                }
            });
        }

        {
            exportMappingsMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {

                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.addChoosableFileFilter(new JsonFileFilter());
                    fileChooser.setFileFilter(new CsvFileFilter());
                    int result = fileChooser.showSaveDialog(exportMappingsMenuItem);
                    if (result == JFileChooser.APPROVE_OPTION) {
                        String filepath = fileChooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                        System.out.println(filepath);
                        if(filepath.endsWith(".csv")) {
                            try {
                                FileWriter fileWriter = new FileWriter(filepath);
                                BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
                                for(Map.Entry<String,String> entry : fieldsMappings.entrySet()) {
                                    bufferedWriter.write(String.format("%s,%s\n", entry.getKey(), entry.getValue()));
                                }
                                bufferedWriter.close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        } else {
                            try {
                                JSONObject mappings = esUtil.getIndexMappings(esIndexs.getSelectedValue().toString());
                                FileWriter fileWriter = new FileWriter(filepath);
                                BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
                                bufferedWriter.write(mappings.toJSONString());
                                bufferedWriter.close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        }
                        statusInfo.append("\n" + String.format("%s表结构导出到文件%s", esIndexs.getSelectedValue(), filepath));
                    }
                }
            });

            importMappingsMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.addChoosableFileFilter(new JsonFileFilter());
                    fileChooser.setFileFilter(new CsvFileFilter());
                    int result = fileChooser.showOpenDialog(importMappingsMenuItem);
                    if (result == JFileChooser.APPROVE_OPTION) {
                        String filepath = fileChooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                        System.out.println(filepath);
                        if(filepath.endsWith(".csv")) {
                            try {
                                FileReader fileReader = new FileReader(filepath);
                                BufferedReader bufferedReader = new BufferedReader(fileReader);
                                String line = null;
                                DefaultTableModel model = (DefaultTableModel) fieldsTable.getModel();
                                while((line = bufferedReader.readLine()) != null) {
                                    String[] fields = Split(line, ',');
                                    model.addRow(fields);
                                }
                                bufferedReader.close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        } else {
                            try {
                                StringBuilder stringBuilder = new StringBuilder();
                                FileReader fileReader = new FileReader(filepath);
                                BufferedReader bufferedReader = new BufferedReader(fileReader);
                                String line = null;
                                while((line = bufferedReader.readLine()) != null) {
                                    stringBuilder.append(line);
                                }
                                bufferedReader.close();

                                JSONObject mappings = JSONObject.parseObject(stringBuilder.toString());
                                if(esUtil.setIndexMappings(esIndexs.getSelectedValue().toString(),mappings)) {
                                    statusInfo.append("\n" + String.format("成功导入文件%s到%s表结构", filepath, esIndexs.getSelectedValue()));
                                }
                                showTableFields();

                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        }

                    }
                }
            });
        }

        {
            reloadSettings.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    showIndexSettings();
                }
            });

            applySettings.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        String text = indexSettings.getText();
                        JSONObject settings = JSONObject.parseObject(text);
                        if (esUtil.setSettings(esIndexs.getSelectedValue().toString(), settings)) {
                            statusInfo.append("\n" + String.format("%s设置更新成功", esIndexs.getSelectedValue().toString()));
                            showIndexSettings();
                        } else {
                            statusInfo.append("\n" + String.format("%s设置更新失败", esIndexs.getSelectedValue().toString()));
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        statusInfo.append("\n" + ex.getMessage());
                    }
                }
            });

            indexSettings.addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent e) {
                    super.keyTyped(e);
                    applySettings.setEnabled(true);
                    reloadSettings.setEnabled(true);
                }
            });
        }

        {
            runAllMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    showSqlQueryResult(sqlTextArea.getText());
                }
            });

            runSelectMenuItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    showSqlQueryResult(sqlTextArea.getSelectedText());
                }
            });
        }
    }

    public MainFrame() {
        createUIComponents();

        addActionListeners();

        loadProperties();
        String esClusters = properties.getProperty("esClusters");
        if (esClusters != null) {
            try {
                List<EsConnectConfig> esConnectConfig = JSONObject.parseArray(esClusters, EsConnectConfig.class);
                if (esConnectConfig != null) {
                    esConnectConfigList = esConnectConfig;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            String[] items = new String[esConnectConfigList.size()];
            int i = 0;
            for (EsConnectConfig item : esConnectConfigList) {
                items[i] = item.getHosts();
                i++;
            }
            esCluster.setModel(new DefaultComboBoxModel(items));
            if(esCluster.getSelectedIndex() >= 0) {
                schema.setSelectedItem(esConnectConfigList.get(esCluster.getSelectedIndex()).getSchema());
                connectUserName.setText(esConnectConfigList.get(esCluster.getSelectedIndex()).getUsername());
                connectPassword.setText(esConnectConfigList.get(esCluster.getSelectedIndex()).getPassword());
            }
        }

    }

    private void initQueryConditions() throws IOException {
        fieldsMappings = esUtil.getMappings(esIndexs.getSelectedValue().toString());
        queryConditionList.clear();
        queryConditionsText.setText("");
        DefaultTableModel defaultTableModel = new DefaultTableModel(new String[][]{}, new String[]{"字段","算符","参数","选中"});
        defaultTableModel.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                //System.out.println(String.format("%d-%d-%d-%d", e.getType(),e.getFirstRow(),e.getLastRow(),e.getColumn()));
                if(e.getType() == 0 && e.getColumn() == 2) {
                    String field = defaultTableModel.getValueAt(e.getFirstRow(), 0).toString();
                    String value = defaultTableModel.getValueAt(e.getFirstRow(), 2).toString();
                    String type = fieldsMappings.get(field);

                    try {
                        switch (type) {
                            case "integer": {
                                Integer.parseInt(value);
                                break;
                            }
                            case "double": {
                                Double.parseDouble(value);
                                break;
                            }
                            case "float": {
                                Float.parseFloat(value);
                                break;
                            }
                            case "boolean": {
                                Boolean.parseBoolean(value);
                                break;
                            }
                        }
                    } catch (NumberFormatException e1) {
                        e1.printStackTrace();
                        statusInfo.append("\n" + String.format("转换字段%s的值%s为类型%s出错", field, value, type));
                        defaultTableModel.setValueAt(null, e.getFirstRow(), 2);
                    }
                }
            }
        });
        queryConditions.setModel(defaultTableModel);
        queryConditions.getColumn("算符").setCellEditor(new DefaultCellEditor(new JComboBox(new String[]{"=","!=",">","<",">=","<="})));
        queryConditions.getColumn("选中").setCellEditor(new DefaultCellEditor(new JCheckBox("选中",true)));
        queryConditions.getColumn("字段").setCellEditor(new DefaultCellEditor(new JComboBox(fieldsMappings.keySet().toArray())));

        queryConditions.setEnabled(true);
        filterButtonAdd.setEnabled(true);
        filterButtonSub.setEnabled(true);
        filterButtonClear.setEnabled(true);
        filterButtonApply.setEnabled(true);
    }

    private void showIndexSettings() {
        try {
            Object selectedIndex = esIndexs.getSelectedValue();
            if (selectedIndex != null) {
                String indexName = selectedIndex.toString();
                JSONObject settings = esUtil.getSettings(indexName);
                indexSettings.setText(settings.toJSONString());

                indexSettings.setEnabled(true);
                applySettings.setEnabled(false);
                reloadSettings.setEnabled(false);
            }
        } catch (IOException e) {
            statusInfo.append("\n" + e.getMessage());
        }
    }

    private void showTableFields() {
        try {
            fieldsMappings = esUtil.getMappings(esIndexs.getSelectedValue().toString());
            Object[][] datas = new Object[fieldsMappings.size()][];
            Object[] columns = new Object[]{"字段名", "字段类型"};

            int i = 0;
            for (String key : fieldsMappings.keySet()) {
                datas[i] = new Object[]{key, fieldsMappings.get(key)};
                i++;
            }

            AppendableTableModel model = new AppendableTableModel(datas, columns);
            model.addTableModelListener(new TableModelListener() {
                @Override
                public void tableChanged(TableModelEvent e) {
                    //System.out.println(JSONObject.toJSONString(e));
                    applyMappings.setEnabled(true);
                }
            });
            fieldsTable.setModel(model);
            fieldsTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(new JComboBox(new String[]{"string", "keyword", "text", "integer", "long", "float", "double", "boolean", "date"})));

            addField.setEnabled(true);
            removeField.setEnabled(true);
            applyMappings.setEnabled(false);
            reloadMappings.setEnabled(true);
            fieldsTable.setEnabled(true);
        } catch (Exception e) {
            statusInfo.append("\n" + e.getMessage());
        }
    }

    private void showPageData() {
        try {
            EsSearchResult esSearchResult = esUtil.search(pageCursor.getIndex(), queryConditionList, pageCursor.getFrom(), pageCursor.getSize());
            pageCursor.setTotal(esSearchResult.getHits().getTotal().getValue());
            pageCursor.setHits(esSearchResult.getHits().getHits().size());
            MyTableModel myTableModel = new MyTableModel(esUtil, pageCursor.getIndex(), esSearchResult.getHits().getHits());
            myTableModel.setStatusInfo(statusInfo);
            myTableModel.addTableModelListener(new TableModelListener() {
                @Override
                public void tableChanged(TableModelEvent e) {
                    System.out.println(JSONObject.toJSONString(e));
                    switch (e.getType()) {
                        case TableModelEvent.INSERT: {
                            statusInfo.append("\n" + String.format("第%d行数据已经插入", e.getFirstRow()));
                            break;
                        }
                        case TableModelEvent.UPDATE: {
                            statusInfo.append("\n" + String.format("第%d行,第%d列数据已更新", e.getFirstRow(), e.getColumn()));
                            break;
                        }
                        case TableModelEvent.DELETE: {
                            if (e.getFirstRow() == e.getLastRow()) {
                                statusInfo.append("\n" + String.format("第%d行数据已删除", e.getFirstRow()));
                            } else {
                                statusInfo.append("\n" + String.format("第%d-%d行数据已删除", e.getFirstRow(), e.getLastRow()));
                            }
                            break;
                        }
                    }
                }
            });
            dataTable.setModel(myTableModel);

            enablePageButtons();
            addRecord.setEnabled(true);
            removeRecord.setEnabled(true);
            dataTable.setEnabled(true);
            statusInfo.append("\n" + String.format("第%d/%d页,共%d条数据", pageCursor.getCurrentPage(), pageCursor.getTotalPages(), pageCursor.getTotal()));
        } catch (IOException e) {
            statusInfo.append("\n" + e.getMessage());
        }
    }

    private void disableIndex() {
        dataTable.setEnabled(false);
        firstPage.setEnabled(false);
        priorPage.setEnabled(false);
        nextPage.setEnabled(false);
        lastPage.setEnabled(false);
        addRecord.setEnabled(false);
        removeRecord.setEnabled(false);

        filterButtonAdd.setEnabled(false);
        filterButtonAdd.setVisible(false);
        filterButtonSub.setEnabled(false);
        filterButtonSub.setVisible(false);
        filterButtonClear.setEnabled(false);
        filterButtonClear.setVisible(false);
        filterButtonApply.setEnabled(false);
        filterButtonApply.setVisible(false);

        fieldsTable.setEnabled(false);
        addField.setEnabled(false);
        applyMappings.setEnabled(false);
        reloadMappings.setEnabled(false);

        indexSettings.setEnabled(false);
        applySettings.setEnabled(false);
        reloadSettings.setEnabled(false);

        sqlTextArea.setEnabled(false);
    }

    private void enablePageButtons() {
        firstPage.setEnabled(true);
        priorPage.setEnabled(true);
        nextPage.setEnabled(true);
        lastPage.setEnabled(true);

        if (pageCursor.isFirstPage()) {
            firstPage.setEnabled(false);
            priorPage.setEnabled(false);
        }
        if (pageCursor.isLastPage()) {
            lastPage.setEnabled(false);
            nextPage.setEnabled(false);
        }
    }

    public static String[] Split(String line, char separator) {
        List<String> result = new ArrayList<>();
        char[] buffer = new char[line.length()];
        int buffer_len = 0;

        for(int i=0; i<line.length(); i++) {
            char c = line.charAt(i);
            if(c == separator) {
                result.add(new String(buffer, 0, buffer_len));
                buffer_len = 0;
            } else {
                buffer[buffer_len++] = c;
            }
        }
        result.add(new String(buffer,0,buffer_len));

        String[] fields = new String[result.size()];
        return result.toArray(fields);
    }

    private int importFromCsv(MyTableModel model, String filepath) {
        List<DocRecord> docRecords = new ArrayList<>();

        try (FileReader fileReader = new FileReader(filepath)) {
            BufferedReader bufferedReader = new BufferedReader(fileReader);

            String head = bufferedReader.readLine();
            String[] columns = Split(head,',');
            String[] targetColumns = model.getColumns();

            if(!Arrays.asList(targetColumns).containsAll(Arrays.asList(columns)))
            {
                String message = String.format("导入文件的字段[%s]不是mapping字段[%s]的子集", String.join(",",columns), String.join(",", targetColumns));
                System.out.println(message);
                statusInfo.append("\n" + message);
                return 0;
            }

            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                String[] values = Split(line,',');
                DocRecord docRecord = new DocRecord();
                docRecord.setSource(new TreeMap<>());

                for (int i = 0; i < columns.length; i++) {
                    String column = columns[i];
                    String value = values[i].isEmpty() ? null : values[i];

                    if (column.equals("_id")) {
                        docRecord.setId(value);
                    } else {
                        docRecord.getSource().put(column, value);
                    }
                }
                docRecords.add(docRecord);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        model.addRows(docRecords);

        return docRecords.size();
    }

    private void exportToCsv(MyTableModel model, String filepath) {

        try {
            FileWriter fileWriter = new FileWriter(filepath);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

            for (int i = 0; i < dataTable.getColumnCount(); i++) {
                if (i == 0) {
                    bufferedWriter.write(dataTable.getColumnName(0));
                } else {
                    bufferedWriter.write(",");
                    bufferedWriter.write(dataTable.getColumnName(i));
                }
            }
            bufferedWriter.write("\n");

            for (int i = 0; i < dataTable.getSelectedRowCount(); i++) {
                int row = dataTable.getSelectedRow() + i;
                for (int j = 0; j < model.getColumnCount(); j++) {
                    if (j == 0) {
                        bufferedWriter.write(dataTable.getValueAt(row, 0).toString());
                    } else {
                        Object value = dataTable.getValueAt(row, j);
                        bufferedWriter.write(",");
                        bufferedWriter.write(value == null ? "" : value.toString());
                    }
                }
                bufferedWriter.write("\n");
            }
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadProperties() {
        try {
            properties.load(new BufferedReader(new InputStreamReader(new FileInputStream("application.properties"))));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读取配置文件application.properties失败");
        }
    }

    private void saveProperties() {
        try {
            properties.store(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("application.properties"))), "");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("写出配置文件application.properties失败");
        }
    }

    private void showSqlQueryResult(String text) {
        try {
            //if (esUtil.connect(esCluster.getSelectedItem().toString(), schema.getSelectedItem().toString(), connectUserName.getText(), new String(connectPassword.getPassword()))) {
            EsSqlTableRecord esSqlTableRecord = null;
            try {
                statusInfo.append("\n" + "执行查询" + text);
                statusInfo.append("\n" + "执行查询" + text);
                esSqlTableRecord = esUtil.sqlQuery(text);
                if (esSqlTableRecord != null) {
                    Object[][] rows = esSqlTableRecord.getRows();
                    Object columns[] = Arrays.stream(esSqlTableRecord.getColumns()).map(field -> field.getName()).toArray();
                    DefaultTableModel model = new DefaultTableModel(rows, columns);
                    sqlQueryTable.setModel(model);
                    statusInfo.append("\n" + "命中" + esSqlTableRecord.getRows().length + "条记录");
                }
            } catch (Exception e) {
                e.printStackTrace();
                String message = e.getMessage();
                statusInfo.append("\n" + e.getMessage());
            }
            //} else {
            //    statusInfo.append("\n" + esCluster + "连接失败");
            //}
        } catch (Exception e) {
            e.printStackTrace();
            statusInfo.append("\n" + esCluster + "连接失败");
        }
    }
}
